<!--
 * @Author: songdeyuan
 * @Date: 2024-01-25 16:22:20
 * @LastEditors: LiSong
 * @LastEditTime: 2025-01-07 15:24:26
 * @Description: 绩效目标表格
-->
<template>
  <div style="display: flex;flex-direction: column;height: 100%; padding-top: 15px;">
    <div>
      <!-- <el-divider content-position="left"
        style="margin: 10px 0">绩效目标</el-divider> -->
      <el-form :model="formValue"
        ref="formRef"
        label-width="180px">
        <el-row>
          <el-col :span="22">
            <el-form-item label="绩效目标"
              placeholder="请输入"
              prop="kpiTarget"
              class="label-right-align"
              :rules="{
                  required: !editDisabled,
                  message: '绩效目标不能为空',
                  trigger: ['blur']
                }">
              <el-input type="textarea"
                maxlength="1000"
                show-word-limit
                :rows="6"
                v-model="formValue.kpiTarget"
                :disabled="editDisabled"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="绩效目标ID"
          v-show="false">
          <el-input type="textarea"
            v-model="formValue.kpiTarget"></el-input>
        </el-form-item>
        <!-- <el-form-item label="项目绩效类型"
          prop="busiTypeCode"
          :rules="{
              required: !editDisabled,
              message: '项目绩效类型必选',
              trigger: ['blur']
            }">
          <rk-select v-model="formValue.busiTypeCode"
            :isSearch="false"
            style="padding: 5px 10px;"
            :disabled="editDisabled"
            enum="COMMON_JXMB_LX_TYPES"></rk-select>
        </el-form-item> -->
      </el-form>
      <!-- <el-divider content-position="left"
        style="margin-bottom: 10px">绩效指标</el-divider> -->
    </div>
    <div style="flex: 1;min-height: 250px;">
      <rk-grid ref="rkGridRef"
        title="绩效指标"
        :boxConfig="false"
        :data="data"
        :columns="columns"
        :loading="loading"
        :editConfig="{ mode: 'row', enabled: !editDisabled }"
        :spanMethod="mergeRowMethod"
        :keepSource="true"
        :pagerConfig="false"
        :toolbarConfig="{ refresh: false }"
        :edit-rules="editRules">
        <template #lv1Perf_default="{ row, column }">
          <span class="bgc full-size">{{ row[column.field] }}</span>
        </template>
        <template #lv2Perf_default="{ row, column }">
          <span>
            {{ row[column.field] }}
          </span>
          <!-- <el-input readonly
            v-model="row[column.field]">
            <template #suffix>
              <el-icon style="margin-left: 5px">
                <circle-plus style="transform:scale(1.5)" />
              </el-icon>
            </template>
          </el-input> -->
        </template>
        <template #lv2Perf_edit="{ row, column }">
          <vxe-pulldown readonly
            ref="level2PullRef"
            destroy-on-close>
            <template #default>
              <el-input readonly
                v-model="row[column.field]"
                @click="showLv2Select(row,'change')">
                <template #suffix>
                  <el-icon class="icon-push"
                    style="margin-left: 5px"
                    @click="showLv2Select(row,'add')">
                    <circle-plus style="transform:scale(1.5)" />
                  </el-icon>
                </template>
              </el-input>
            </template>
            <template #dropdown>
              <div class="dropdown">
                <div class="list-item2"
                  v-for="item in currentLv2Data"
                  :key="item.lv2PerfIndId"
                  @click="selectLv2Event(item,row)">
                  <span>{{ item.lv2PerfIndName }}</span>
                </div>
              </div>

            </template>
          </vxe-pulldown>
        </template>
        <template #lv3Perf_edit="{ row, column }">
          <vxe-pulldown ref="lv3PulldownRef"
            class="rk-tree-select"
            destroy-on-close>
            <template #default>
              <vxe-input v-model="row[column.field]"
                placeholder="请输入"
                @focus="focusEvent(row)"></vxe-input>
            </template>
            <template #dropdown>
              <div class="rk-tree-select-dropdown-content">
                <el-tree class="rk-tree-select-center"
                  :data="currentTreeData"
                  :props="lv3TreeProps"
                  v-loading="treeloading"
                  :highlight-current="true"
                  @node-click="handleNodeClick($event,row)">
                </el-tree>
              </div>
            </template>
          </vxe-pulldown>
        </template>
        <template #kpiValType_edit="{ row, column }">
          <rk-select dist="DSY_V_ELE_XMJX_ZBZLX"
            :transfer="true"
            :show-code="false"
            :isSearch="false"
            v-model="row['kpiEvalstd']"
            :labelConfig="{ value:'id',label:'name'}"
            @change="kpiValChange($event,row)" />
        </template>

        <template #kpiVal_edit="{ row, column }">
          <vxe-input v-model="row[column.field]" ></vxe-input>
        </template>
        <template #unit_edit="{ row, column }">
          <vxe-input v-model="row[column.field]" ></vxe-input>
        </template>
        <template #kpiContent_edit="{ row, column }">
          <vxe-input v-model="row[column.field]"></vxe-input>
        </template>
        <template #kpiRemark_edit="{ row, column }">
          <vxe-input v-model="row[column.field]"></vxe-input>
        </template>

        <template #operation="{ row }">
          <el-button type="danger"
            size="small"
            :disabled="row.disabled"
            @click="handleOperation('delete',row)">删除
          </el-button>
        </template>
      </rk-grid>
    </div>
  </div>
</template>

<script setup name="ProjectJxmbTable">
import { CirclePlus } from '@element-plus/icons-vue';
import { computed, onMounted, reactive, ref } from 'vue';

import { defAxios as request } from '@/utils/http';
import { FormType } from '@fp/config/form-pojo';

import RkSelect from "@/components/select/src/RkSelect.vue";


// 向上触发的方法
const emits = defineEmits(['setFormItemValue']);

const props = defineProps({
  // 表单数据信息
  formData: {
    type: Object,
    default: () => {
      return { proId: '' };
    },
  },
  formType: { type: String },
});

const formRef = ref(null)
const loading = ref(false);
const firstLoad = ref(false)
const treeloading = ref(false);
const level2PullRef = ref()
const lv3PulldownRef = ref()

const lv2ApiData = ref({})
const currentLv2Data = ref([])
const currentTreeData = ref([])

const formValue = reactive({
  kpiTarget: '',
  kpiPerId: '',
  busiTypeCode: '2',
  fiscalYear: ''
})

const lv3TreeProps = { 
  code: 'indicatorId',
  label: 'perfIndName',
  value: 'perfIndCode',
  children: 'children'
}

// 允许编辑的表单类型
const allowEditTyps = ['add', 'edit']
// 是否禁用编辑
const editDisabled = computed(() => {
  return !allowEditTyps.includes(props.formType)
})


// 表格的模板引用
const rkGridRef = ref();
const editType = ref("add")
// ----- 表格相关操作
const editRules = {
  lv1PerfIndName: [
    { required: true, message: '一级指标必须填写' }
  ],
  lv2PerfIndName: [
    { required: true, message: '二级指标必须填写' }

  ],
  lv3PerfIndName: [
    { required: true, message: '三级指标必须填写' }

  ],
  kpiEvalstdName: [
    { required: true, message: '指标值类型必须填写' }
  ],
  kpiVal: [
    { required: true, message: '指标值必须填写' }
  ],
  unit: [
    { required: true, message: '' }
  ]
}
const defaultData = {
  lv1PerfIndId: '',
  lv2PerfIndId: '',
  lv1PerfIndCode: '',
  lv2PerfIndCode: '',
  lv2PerfIndName: '',
  lv3PerfIndName: '',
  kpiEvalstdName: '',
  kpiVal: '',
  unit: '',
  kpiContent: '',
  kpiRemark: ''
};
const queryParam = reactive({
  map: void 0,
  proId: '',
  fiscalYear: props.formData.FISCAL_YEAR
});
const data = ref([]);
const columns = computed(() => {
  let columns = [
    {
      title: '分解指标',
      width: 120,
      align: 'center',
      children: [
        {
          field: 'lv1PerfIndId',
          visible: false
        }, {
          field: 'lv2PerfIndId',
          visible: false
        }, {
          field: 'lv1PerfIndCode',
          visible: false
        }, {
          field: 'lv2PerfIndCode',
          visible: false
        }, {
          field: 'lv3PerfIndCode',
          visible: false
        }, {
          field: 'lv3PerfIndId',
          visible: false
        },
        {
          field: 'lv1PerfIndName',
          title: '一级指标',
          width: 120,
          align: 'center',
          slots: { default: 'lv1Perf_default' },
        },
        {
          field: 'lv2PerfIndName',
          title: '二级指标',
          width: 200,
          align: 'center',
          editRender: { autofocus: '.el-input__inner' },
          slots: { default: 'lv2Perf_default', edit: 'lv2Perf_edit' },
        },
        {
          field: 'lv3PerfIndName',
          title: '三级指标',
          width: 235,
          align: 'center',
          editRender: { autofocus: '.vxe-input--inner' },
          slots: { edit: 'lv3Perf_edit' },
        },
        {
          field: 'kpiEvalstdName',
          title: '指标值类型',
          width: 180,
          align: 'center',
          editRender: { autofocus: '.vxe-input--inner', autoselect: true },
          slots: { edit: 'kpiValType_edit' },
        },
        {
          field: 'kpiVal',
          title: '指标值',
          width: 150,
          align: 'left',
          editRender: { autofocus: '.vxe-input--inner' },
          slots: { edit: 'kpiVal_edit' },
        },
        {
          field: 'unit',
          title: '度量单位',
          width: 150,
          align: 'left',
          editRender: { autofocus: '.vxe-input--inner' },
          slots: { edit: 'unit_edit' },
        },
        {
          field: 'kpiContent',
          title: '指标值解释',
          // width: 235,
          align: 'left',
          editRender: { autofocus: '.vxe-input--inner' },
          slots: { edit: 'kpiContent_edit' },
        },
        {
          field: 'kpiRemark',
          title: '指标值说明',
          // width: 220,
          align: 'left',
          editRender: { autofocus: '.vxe-input--inner' },
          slots: { edit: 'kpiRemark_edit' },
        },]
    },
    {
      field: 'operation', title: '操作', width: 150, fixed: 'right',
      showOverflow: true, align: 'center',
      visible: !editDisabled.value, slots: { default: 'operation' }
    }
  ];
  return columns
});

//三级指标获取焦点事件
const focusEvent = async (row) => {
  const lv3pulldown = lv3PulldownRef.value
  if (!lv3pulldown) {
    return
  }
  const queryParams = { indId: row['lv2PerfIndId'] }
  treeloading.value = true
  lv3pulldown.showPanel()
  try {
    const res = await request({
        url: 'proResApply/proPerformanceIndicatorById',
        method: 'post',
        data: queryParams
    })
    const { code, data } = res
    if (code === 200) {
      currentTreeData.value = data
    }
    treeloading.value = false
  } catch (e) {
    treeloading.value = false
  }

}

/** 树节点点击 */
const handleNodeClick = async (data, row) => {
  row['lv3PerfIndName'] = data.perfIndName
  row['lv3PerfIndId'] = data.indicatorId
  row['lv3PerfIndCode'] = data.perfIndCode
  await rkGridRef.value.reloadRow(row);
  lv3PulldownRef.value.hidePanel()
};

const kpiValChange = async (data, row) => {
  row['kpiEvalstdName'] = data[0].label
  row['kpiEvalstd'] = data[0].value
  await rkGridRef.value.reloadRow(row);

}

/** 展示二级指标下拉框*/
const showLv2Select = (row, type) => {
  const lv2pulldown = level2PullRef.value
  editType.value = type
  if (!lv2pulldown) {
    return
  }
  currentLv2Data.value = lv2ApiData.value[row.lv1PerfIndId]
  lv2pulldown.showPanel()
}

/** 选中二级下拉框事件*/
const selectLv2Event = async (item, row) => {
  if (editType.value === 'add') {
    const defaultRow = Object.assign({}, defaultData,
      {
        lv1PerfIndName: item["lv1PerfIndName"],
        lv2PerfIndName: item["lv2PerfIndName"],
        lv1PerfIndId: item["lv1PerfIndId"],
        lv2PerfIndId: item["lv2PerfIndId"],
        lv1PerfIndCode: item["lv1PerfIndCode"],
        lv2PerfIndCode: item["lv2PerfIndCode"],
      })
    await rkGridRef.value.insertAt(defaultRow, row);
    const { fullData } = rkGridRef.value.getTableData();
    const updateRows = fullData.filter(item => {
      return item["lv1PerfIndId"] === row["lv1PerfIndId"]
    }).map(data => {
      data.disabled = void 0;
    })
    await rkGridRef.value.reloadRow(updateRows);
    level2PullRef.value.hidePanel()
    return
  }
  row['lv2PerfIndName'] = item["lv2PerfIndName"]
  row['lv2PerfIndId'] = item['lv2PerfIndId']
  row['lv2PerfIndCode'] = item['lv2PerfIndCode']
  await rkGridRef.value.reloadRow(row);
  level2PullRef.value.hidePanel()
}

/** 处理新增行删除行 */
const handleOperation = async (buttonType, row) => {
  if (buttonType === 'delete') {
    const { fullData } = rkGridRef.value.getTableData();
    const existRows = fullData.filter(item => {
      return item["lv1PerfIndId"] === row["lv1PerfIndId"]
    })
    if (existRows.length > 1) {
      rkGridRef.value.remove(row);
    }
    if (existRows.length <= 2) {
      existRows.forEach(item => item.disabled = true)
    }
  }
};

// ----- 获取组件数据
/**
 * 暴露给表单调用，固定名称getCompData
 */
const getCompData = function () {
  const { fullData } = rkGridRef.value.getTableData();
  return {
    pro_jxmb: { grid: JSON.parse(JSON.stringify(fullData)), ...formValue },
  };
};

// ----- 校验组件数据
const jxmbTabName = '绩效目标';
/**
 * 暴露给表单调用，固定名称validateData
 * 
 * @param extParams { checkRequired 是否校验必填 checkLength 是否校验长度 } 
 */
const validateData = async (extParams) => {
  // 返回结果定义
  let result = { valid: false, message: `${jxmbTabName}：校验不通过！` }
  // 条件参数定义
  if (!extParams) extParams = { checkRequired: true, checkLength: true }

  // 表单校验
  if (extParams.checkRequired) {
    try {
      await formRef.value.validate()
    } catch (e) {
      result.message = `${jxmbTabName}：请检查必填项，以及未通过校验项！`
      return result
    }
  }
  // 校验表格数据
  const { fullData } = rkGridRef.value.getTableData();
  // 非禁用时，校验数据
  if (!editDisabled.value) {
    result = jxzbTableDataCheck(fullData, extParams)
    return result
  } else { 
    result.valid = true
    result.message = '校验通过！'
    return result
  }
};

// 校验的字段定义
const checkColumn = {
  // 长度字段
  lengthCols: [
    { field: 'lv3PerfIndName', title: '三级指标', maxLength: 500 },
    { field: 'kpiVal', title: '指标值', maxLength: 500 },
    { field: 'kpiContent', title: '指标值解释', maxLength: 1000 },
    { field: 'kpiRemark', title: '指标值说明', maxLength: 1000 },
  ],
  // 必填字段
  requiredCols: [
    { field: 'lv3PerfIndName', title: '三级指标' },
    { field: 'kpiEvalstdName', title: '指标值类型' },
    { field: 'kpiVal', title: '指标值' },
    { field: 'unit', title: '度量单位' },
  ]
}
/**
 * 绩效指标表格数据校验
 * 
 * @param tableData 表格数据
 * @param extParams { checkRequired 是否校验必填 checkLength 是否校验长度 } 
 */
const jxzbTableDataCheck = (tableData, { checkRequired=true, checkLength=true }) => {
  const result = { valid: false, message: `${jxmbTabName}：校验不通过！` };
  if (!tableData || tableData.length === 0) return result

  for (let row of tableData) {
    // 必填校验
    if (checkRequired) {
      for (let vdItem of checkColumn.requiredCols) {
        // 指标类型包含定性值，度量单位不做必填校验
        if (vdItem.field === 'unit' && row['kpiEvalstdName'].includes('定性值')) {
          continue;
        }
        // 其他属性为空校验
        if (!row[vdItem.field]) {
          result.message = `${jxmbTabName}：【${vdItem.title}】内容不能为空！`;
          return result
        }
      }
    }

    // 长度校验
    if (checkLength) {
      for (let lenItem of checkColumn.lengthCols) {
        let value = row[lenItem.field]
        if (value && value.length > lenItem.maxLength) {
          result.message = `${jxmbTabName}：【${lenItem.title}】内容不能超过${lenItem.maxLength}字，请检查！`;
          return result
        }
      }
    }
  }
  result.valid = true
  result.message = `${jxmbTabName}：校验通过！`
  return result
}

/** 加载数据 */
const loadData = async () => {
  const { proId } = props.formData;
  queryParam.proId = proId;
  if (!FormType.ADD.equals(props.formType) && firstLoad.value) {
    const proIndicator = await request({
        url: 'proResApply/queryProIndicatorByProId',
        method: 'post',
        data: queryParam
    });
    if (proIndicator.code === 200) {
      if (proIndicator.data.list.length > 0) {
        data.value = proIndicator.data.list
        formValue.kpiTarget = proIndicator.data.kpiTarget
        formValue.kpiPerId = proIndicator.data.kpiPerId
        formValue.busiTypeCode = proIndicator.data.busiTypeCode
        formValue.fiscalYear = proIndicator.data.fiscalYear
      } else {
        firstLoad.value = false
      }
    }
  }
}

/** 加载基础数据 */
const loadInitBasicData = async () => {
  queryParam.fiscalYear = props.formData.FISCAL_YEAR
  const res = await request({
    url: 'proResApply/proPerformanceIndicator',
    method: 'post',
    data: queryParam
  });
  if (res.code === 200) {
    // 取消数组引用问题
    const resData = JSON.parse(JSON.stringify(res.data))
    if (FormType.ADD.equals(props.formType) || !firstLoad.value) {
      data.value = res.data
    }
    let lv2Api = {}
    for (let item of resData) {
      if (!lv2Api[item.lv1PerfIndId]) {
        lv2Api[item.lv1PerfIndId] = [item]
        continue
      }
      lv2Api[item.lv1PerfIndId].push(item)
    }
    lv2ApiData.value = lv2Api
  }
}

/** 合并行 */
const mergeRowMethod = ({ row, _rowIndex, column, visibleData }) => {
  const fields = ['lv1PerfIndName'];
  const cellValue = row[column.field];
  if (cellValue && fields.includes(column.field)) {
    const prevRow = visibleData[_rowIndex - 1];
    let nextRow = visibleData[_rowIndex + 1];
    if (prevRow && prevRow[column.field] === cellValue) {
      return { rowspan: 0, colspan: 0 };
    } else {
      let countRowspan = 1;
      while (nextRow && nextRow[column.field] === cellValue) {
        nextRow = visibleData[++countRowspan + _rowIndex];
      }
      if (countRowspan > 1) {
        return { rowspan: countRowspan, colspan: 1 };
      }
    }
  }
};
// watch(() => props.formData.FISCAL_YEAR,
//   (newValue, oldValue) => {
//     initData();
//   },
//   { deep: false, immediate: false }
// )

//请求初始化数据
onMounted(async () => {
  firstLoad.value = true
  await initData()
});

const initData = async () => {
  loading.value = true;
  if (!props.formData.FISCAL_YEAR && FormType.EDIT.equals(props.formType)) {
    return
  }
  await loadData()

  //更新和新增调用加载基础数据
  if (FormType.EDIT.equals(props.formType) || FormType.ADD.equals(props.formType)) {
    await loadInitBasicData()
  }
  loading.value = false;
  firstLoad.value = false
}

defineExpose({
  getCompData,
  validateData
});

</script>

<style lang="scss" scoped>
.rk-tree-select {
	width: 100%;

	:deep(.vxe-pulldown--panel) {
		z-index: 99999 !important;
	}

	:deep(.vxe-pulldown--wrapper) {
		border-radius: 4px 4px 0 0;
	}
}

.full-size {
	position: absolute;
	width: calc(100% - 1px);
	height: calc(100% - 1px);
	top: 0;
	left: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0 10px;
}

.bgc {
	background-color: #e6e6e6;
}

.list-item2 {
	line-height: 22px;
	padding: 5px 0px 5px 24px;
}

.list-item2:hover {
	background-color: #f5f7fa;
}

.dropdown {
	min-height: 100px;
	max-height: 300px;
	overflow: auto;
	border: 1px solid #dcdfe6;
}

.icon-push:hover {
	cursor: pointer;
}

:deep(.vxe-input.type--float .vxe-input--inner) {
	padding-right: 1.8em !important;
}

:deep(.vxe-input.type--float .vxe-input--suffix.is--clear) {
	right: 0.2em !important;
}

:deep(.vxe-input.type--float .vxe-input--extra-suffix) {
	display: none !important;
}

.rk-tree-select-dropdown-content {
	min-height: 100px;
	max-height: 300px;
	overflow: auto;
	// border: 1px solid #dcdfe6;
	border-radius: var(--vxe-border-radius);
	border: 1px solid var(--vxe-table-popup-border-color);
	box-shadow: 0 0 6px 2px rgba(0, 0, 0, 0.1);
	.clear-icon {
		cursor: pointer;
	}
	.rk-tree-select-center {
		padding: 5px 0;
		:deep(.el-tree-node__content) {
			padding-right: 24px;
			.el-tree-node__label {
				flex: 1;
			}
		}
	}
}
</style>
